﻿using System;

namespace Fx.Caching
{
    public interface ICache
    {
        /// <summary>
        /// Check cache for item. If there, retrieve it. If item is not in cache, retrieve from repository
        /// and return item retrieved from repository.  Do not serialize items to disc.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cacheID">key in cache of item (case insensitive)</param>
        /// <param name="getItemCallback">Repository method call to use if cache is empty</param>
        /// <param name="cacheDurationMinutes">Number of minutes to keep item in cache</param>
        /// <returns></returns>
        T Get<T>(string cacheId, Func<T> getItemCallback, int cacheDurationMinutes) where T : class;

        /// <summary>
        /// Check cache for item. If there, retrieve it. If item is not in cache, retrieve from repository
        /// and return item retrieved from repository.  Do not serialize items to disc.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cacheId">key in cache of item (case insensitive)</param>
        /// <param name="getItemCallback">Repository method call to use if cache is empty</param>
        /// <param name="cacheDurationMinutes">Number of minutes to keep item in cache</param>
        /// <param name="withSerialization">Whether or not to serialize item in case for use if getItemCallback fails</param>
        /// <returns></returns>
        T Get<T>(string cacheId, Func<T> getItemCallback, int cacheDurationMinutes, bool withSerialization) where T : class;

        /// <summary>
        /// Check cache for item. If there, retreive it. If item is not in cache, return null.
        /// Independently check the expiration for the cacheId (case insensitive) passed in.  If expired, retrieve from repository
        /// in an asynch call and populate cache in the background.  This method will not wait for repository 
        /// call to finish before returning.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cacheId">key in cache of item (case insensitive)</param>
        /// <param name="getItemCallback">Repository method call to use if cache is empty</param>
        /// <param name="cacheDurationMinutes">Number of minutes to keep item in cache</param>
        /// <param name="withSerialization">Whether or not to serialize item in case for use if getItemCallback fails</param>
        /// <returns></returns>
        T GetAsynch<T>(string cacheId, Func<T> getItemCallback, int cacheDurationMinutes, bool withSerialization) where T : class;
    }
}
